package com.unittec.drainage.provider.auth.excel.export;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.unittec.drainage.provider.common.RabbitConstants;
import com.unittec.drainage.provider.log.Log;
import com.unittec.drainage.sdk.root.domain.GatewayRequest;
import com.unittec.drainage.sdk.root.domain.Result;

/**
 * @Description: EXCEL导出异步消费创建方法
 * @Author: wuxinwei
 * @CreateDate: 2019/11/19 13:39
 */
@Service
public class MqExcelExportProducerService implements RabbitTemplate.ConfirmCallback {

    Map<String, GatewayRequest<?>> reqMap = new ConcurrentHashMap<>(16);
    Map<String, Boolean> resMap = new ConcurrentHashMap<>(16);
    @Autowired
    private Log log;

    private RabbitTemplate rabbitTemplate;

    @Autowired
    public MqExcelExportProducerService(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        // rabbitTemplate如果为单例的话，那回调就是最后设置的内容
        rabbitTemplate.setConfirmCallback(this);
    }

    private CorrelationData logreq(GatewayRequest<?> req) {
        String id = StringUtils.isBlank(req.getRequestId()) ? UUID.randomUUID().toString() : req.getRequestId();
        CorrelationData correlationId = new CorrelationData(id);
        log.debug(req, "{} 消息投递", correlationId.toString());
        reqMap.put(id, req);

        return correlationId;
    }

    private boolean waitResponse(GatewayRequest<?> req, CorrelationData correlationId) {
        try {
            synchronized (req) {
                req.wait(1000);
            }
        } catch (InterruptedException e) {
        }

        boolean ret = resMap.get(correlationId.getId()) == null ? false : resMap.remove(correlationId.getId());

        if (!ret) {
            log.error(req, "消息发送失败");
            throw Result.exception("消息发送失败");
        }

        return ret;
    }

    public <T> boolean createExcelExportMsg(GatewayRequest<T> req) {
        CorrelationData correlationId = logreq(req);
        rabbitTemplate.convertAndSend(RabbitConstants.EXCHANGE_DIRECT, RabbitConstants.ROUTINGKEY_EXPORT_EXCEL,
            req.getContent(), correlationId);
        try {
            return waitResponse(req, correlationId);
        } catch (Exception e) {
            log.error(req, "消息发送失败", e);
            return false;
        }
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (correlationData == null) {
            return;
        }
        GatewayRequest<?> req = reqMap.remove(correlationData.getId());
        if (null != req) {
            synchronized (req) {
                resMap.put(correlationData.getId(), ack);
                req.notifyAll();
            }

            // 回调方法中不能拿到请求相关的鉴权信息，不记录正常日志
            if (!ack) {
                String logmsg = String.format("confirm requestId=[%s] appId=[%s], rid=[%s], cause=[%s]",
                    req.getRequestId(), req.getAppId(), correlationData.toString(), cause);
                log.sysErrLog("MQconfirm", logmsg, null);
            }
        }
    }
}
